package com.qdlc.p2p.dal.common;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.qdlc.p2p.common.util.StringUtil;
import com.qdlc.p2p.dal.checkrule.RuleCheck;
import com.qdlc.p2p.dal.dao.RuleDao;
import com.qdlc.p2p.dal.dto.Rule;

/**
 * RuleCheck配置文件工具类
 *
 * @author linya 2016-01-26
 */
@Service
public class RuleCheckHelper implements ApplicationContextAware {

    private static final Map<Class<? extends RuleCheck>, RuleCheck> ruleCheckMap = new ConcurrentHashMap<Class<? extends RuleCheck>, RuleCheck>();

    private static final String RULE_PACKAGE_NAME = "com.qdlc.p2p.dal.checkrule";

    /**
     * 根据nid获取配置值
     *
     * @param ruleClazz
     * @return
     */
    public static <T extends RuleCheck> T getValue(Class<T> ruleClazz) {
        T t = getFromCacheOrDB(ruleClazz, true);
        return t;
    }

    /**
     * 从缓存或者数据库中获取数据
     * 如果cached=true，先从缓存中查找，如果没有，然后从数据库查找。
     * 如果cached=false，强制从数据库获取，并将获取的数据存放到缓存中去。
     *
     * @param clazz
     * @param cached
     * @return
     */
    @SuppressWarnings("unchecked")
    private static <T extends RuleCheck> T getFromCacheOrDB(Class<T> clazz, boolean cached) {
        T t = null;
        if (cached) {
            t = (T) ruleCheckMap.get(clazz);
        }
        return t;
    }

    /**
     * 初始化配置信息
     *
     * @param context
     */
    @SuppressWarnings("unchecked")
    private static void initial(ApplicationContext context) {
        RuleDao ruleDao = context.getBean(RuleDao.class);
        List<Rule> list = ruleDao.findAll();
        if (list != null) {
            for (Rule rule : list) {
                try {
                    Class<?> clazz = Class.forName(RULE_PACKAGE_NAME + "." + StringUtil.firstCharUpperCase(rule.getNid()) + "RuleCheck");
                    if (!RuleCheck.class.isAssignableFrom(clazz)) {
                        continue;
                    }

                    Class<? extends RuleCheck> ruleClass = (Class<? extends RuleCheck>) clazz;
                    Object jsonObj = JSON.parseObject(rule.getRuleCheck(), ruleClass);
                    if (jsonObj == null) {
                        clazz.newInstance();
                    } else {
                        ruleCheckMap.put(ruleClass, (RuleCheck) jsonObj);
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        initial(applicationContext);
    }
}
